/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.chl.groupofdoom.jpa;

import edu.chl.groupofdoom.entities.Torrent;
import edu.chl.groupofdoom.entities.User;
import edu.chl.groupofdoom.enums.Category;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class Mapper {

    private final static EntityManagerFactory emf = Persistence.createEntityManagerFactory("project_pu");

    /**
     * Retrieves a Torrent-object from the database
     *
     * @param id
     * @return a torrent object with the specified id
     */
    public static Torrent getTorrent(Long id) {
        EntityManager em = emf.createEntityManager();
        em = emf.createEntityManager();
        Torrent torrent = em.find(Torrent.class, id);
        em.close();
        return torrent;
    }

    /**
     * Removes a torrent-object from the database
     * 
     * @param id
     */
    public static void removeTorrent(long id) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        tx.begin();
        Torrent t = em.find(Torrent.class, id);
        em.remove(t);
        tx.commit();

        em.close();
    }

    /**
     * Searches the database for Torrent-objects matching the searchQuery
     *
     * @param searchQuery
     * @param maxresults number of results to retrieve
     * @return a list of Torrent objects
     */
    public static List<Torrent> searchForTorrents(String searchQuery, int maxresults) {
        List<Torrent> torrents = new ArrayList<Torrent>();
        try {
            EntityManager em = emf.createEntityManager();
            em = emf.createEntityManager();
            Query q = em.createQuery("SELECT t from Torrent t WHERE t.name LIKE '%" + searchQuery + "%'");
            if(maxresults > -1)
                q.setMaxResults(maxresults);
            torrents = (List<Torrent>) q.getResultList();
            em.close();
        } catch (Exception e) {
            System.out.println("MAPPER.searchForTorrents() FAILED: " + e.toString());
        }
        return torrents;
    }

    /**
     * Searches the database for torrent names matching the searchQuery
     * 
     * @param searchQuery
     * @return
     */

    public static List<String> searchForTorrentNames(String searchQuery) {
        List<String> torrentNames = null;
        try {
            EntityManager em = emf.createEntityManager();
            em = emf.createEntityManager();
            Query q = em.createQuery("SELECT t.name from Torrent t WHERE t.name LIKE '%" + searchQuery + "%'");
            q.setMaxResults(5);
            torrentNames = (List<String>) q.getResultList();
            em.close();
        } catch (Exception e) {
            System.out.println("MAPPER.searchForTorrents() FAILED: " + e.toString());
        }
        return torrentNames;
    }

    /**
     * Searches the database for torrent names matching the category
     *
     * @param category
     * @return a list of Torrent objects
     */
    public static List<Torrent> browseTorrents(Category category) {
        List<Torrent> torrents = new ArrayList<Torrent>();
        try {
            EntityManager em = emf.createEntityManager();
            em = emf.createEntityManager();
            Query q = em.createQuery("SELECT t from Torrent t WHERE t.category = edu.chl.groupofdoom.enums.Category." + category.name());
            torrents = (List<Torrent>) q.getResultList();
            em.close();
        } catch (Exception e) {
            System.out.println("MAPPER.browseTorrents() FAILED: " + e.toString());
        }
        return torrents;
    }

    /**
     * Searches the database for torrent-objects of the parameter user
     * 
     * @param user
     * @return
     */
    public static List<Torrent> getUsersTorrents(User user) {
        List<Torrent> torrents = new ArrayList<Torrent>();
        try {
            EntityManager em = emf.createEntityManager();
            em = emf.createEntityManager();
            Query q = em.createQuery("SELECT t from Torrent t WHERE t.user.id = " + user.getId() + "'");
            torrents = (List<Torrent>) q.getResultList();
            em.close();
        } catch (Exception e) {
            System.out.println("MAPPER.searchForTorrents() FAILED: " + e.toString());
        }
        return torrents;
    }

    /**
     * Registers a user to the database
     * 
     * @param username
     * @param hashedPassword hashed method not implemented yet
     * @param email
     * @param admin
     * @return true if succeed
     */
    public static boolean registerUser(User user) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        try {
            tx.begin();
            em.persist(user);
            tx.commit();

        } catch (Exception e) {
            return false;
        } finally {
            em.close();
        }
        return true;
    }

    /**
     * Adds a torrent to the database
     *
     * @param torrent
     * @param user
     * @return
     */
    public static boolean addTorrent(Torrent torrent) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            em.persist(torrent);
            tx.commit();

        } catch (Exception e) {
            return false;
        } finally {
            em.close();
        }
        return true;
    }

    /**
     * Updates a torrent in the database.
     * Used by the addComment method
     * 
     * @param torrent
     * @return true if success
     */

    public static boolean updateTorrent(Torrent torrent) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            em.merge(torrent);
            tx.commit();

        } catch (Exception e) {
            return false;
        } finally {
            em.close();
        }
        return true;
    }

    /**
     * Checks if parameter username exists in the database
     *
     * @param username
     * @return true if not exists
     */
    public static boolean isUsernameUnique(String username) {
        EntityManager em = emf.createEntityManager();
        Query q = em.createQuery("SELECT u from User u WHERE u.username = '" + username + "'");
        boolean unique = q.getResultList().isEmpty();
        em.close();
        return unique;
    }

    /**
     * Checks if parameter email exists in the database
     * 
     * @param email
     * @return true if not exists
     */
    public static boolean isEmailUnique(String email) {
        EntityManager em = emf.createEntityManager();
        Query q = em.createQuery("SELECT u from User u WHERE u.email = '" + email + "'");
        boolean unique = q.getResultList().isEmpty();
        em.close();
        return unique;
    }

    /**
     * Retrieves a User-object from the database.
     *
     * @param username
     * @param password
     * @return user variable, points to null if username and password does not exists in database.
     */
    public static User login(String username, String password) {
        EntityManager em = emf.createEntityManager();
        //Query for a List of PurchaseOrders
        Query q = em.createQuery("SELECT u from User u WHERE u.username = '" + username + "' AND u.hashedPassword = '" + password + "'");
        System.out.println(q.toString());
        User user = null;
        try {
            user = (User) q.getSingleResult();
        } catch (javax.persistence.NoResultException e) {
            e.printStackTrace();
        } catch (ClassCastException e) {
            e.printStackTrace();
        }
        em.close();
        return user;
    }
}
